import { _decorator, Component, Prefab, instantiate, Node, Vec3, CCInteger, ParticleSystem, RigidBody, KeyCode} from 'cc';
import { InputEx } from './Utils/InputEx';
const { ccclass, property } = _decorator;

@ccclass('BoxCreateManager')
export class BoxCreateManager extends Component {
    @property({type: Prefab})
    public boxPrfb: Prefab = null;

    @property({type: Prefab})
    smallExplosion: Prefab = null;

    @property({type: CCInteger})
    public bottomBoxNum: number = 5;

    @property({type: CCInteger})
    explosionRadius: number = 10;

    @property({type: CCInteger})
    explosionForce: number = 100;

    @property(Node)
    boxPool: Node = null;

    boomEnd: boolean = false;

    start () {
        // Your initialization goes here.
        setTimeout(()=>{
            this.generateBoxes();
        }, 1000)
    }

    generateBoxes() {
        const bottomBoxNum = this.bottomBoxNum;
        const boxSize = 1;
        for (let i = 0; i < bottomBoxNum; i++) {   
            for (let j = 0; j < (bottomBoxNum - i); j++) {
                const boxNode:Node = instantiate(this.boxPrfb);
                const posX = i * (0.7 / 2) + j * 0.7;
                const posY = 4 + i * 0.5;
                boxNode.parent = this.boxPool;
                boxNode.setPosition(new Vec3(posX, posY, 0));
            }
        }
    }

    generateExplosion () {
        // 实例化爆炸物预制体，并添加到场景中
        var explosion = instantiate(this.smallExplosion);
        this.node.addChild(explosion);
        // 播放爆炸粒子特效
        var particle = explosion.getComponent(ParticleSystem);
        particle.play();
        // 获取所有盒子的物理刚体组件，对他们施加冲力
        var rigidBodys = this.boxPool.getComponentsInChildren(RigidBody);
        rigidBodys.forEach((r)=>{
            if (r) {
                const dir = new Vec3();
                // 计算盒子刚体与爆炸源的空间距离
                Vec3.subtract(dir, r.node.getWorldPosition(), explosion.getWorldPosition());
                const dist: number = dir.length();
                // 如果盒子与爆炸源的距离不超过爆炸范围半径的话，则对该盒子刚体施加冲力
                if (dist < this.explosionRadius) {
                    // 根据盒子与爆炸源的距离创建不同的冲力向量，盒子离得越近，则冲力越大
                    dir.normalize();
                    Vec3.multiplyScalar(dir, dir, this.explosionForce / dist);
                    // 对刚体施加冲力
                    r.applyImpulse(dir);
                }
            }
        })
    }

    lateUpdate(dt: number): void {
        if (!this.boomEnd) {
            if (InputEx.GetKeyDown(KeyCode.KEY_E)) {
                this.boomEnd = true;
                this.generateExplosion();
            }
        }
    }
}
